home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Languages Suite
/
ProgramD2.iso
/
Borland
/
Borland C++ V5.02
/
CLASSSRC.PAK
/
OBJSTRM.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-06
|
17KB
|
767 lines
//----------------------------------------------------------------------------
// Borland Class Library
// Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
//
//$Revision: 5.9 $
//
//----------------------------------------------------------------------------
#include <classlib/pch.h>
#include <classlib/streambl.h>
#include <classlib/objstrm.h>
#include <services/checks.h>
#include <services/cstring.h>
#include <services/memory.h>
#include <tchar.h>
DIAG_DEFINE_GROUP(Objstrm,1,0);
const uint32 streamVersion = 0x0101;
const _TCHAR versionIndicator = ':';
const _TCHAR EOS = '\0';
const uint8 oldNullStringLen = UCHAR_MAX;
const uint32 nullStringLen = ULONG_MAX;
TStreamableTypes *pstream::types = 0;
const _TCHAR *TStreamer::StreamableName() const
{
return 0;
}
TStreamableClass::TStreamableClass( const _TCHAR *n,
BUILDER b,
int d,
ModuleId id ) :
ObjectBuilder( b, d ),
ModId(id)
{
ObjectId = new _TCHAR[_tcslen(n)+1];
_tcscpy( CONST_CAST(_TCHAR *,ObjectId), n );
pstream::initTypes();
if( id != 0 ) // id == 0 is used only during lookup.
// It flags an instance that shouldn't be registered
pstream::types->RegisterType( id, *this );
}
TStreamableClass::~TStreamableClass()
{
if( ModId != 0 )
pstream::types->UnRegisterType( ModId, *this );
delete [] CONST_CAST(_TCHAR *,ObjectId);
}
void TStreamableTypes::RegisterType( ModuleId, TStreamableClass& ts )
{
Types.Add(&ts);
}
void TStreamableTypes::UnRegisterType( ModuleId, TStreamableClass& ts )
{
Types.Detach(&ts);
if( Types.Count() == 0 )
pstream::releaseTypes();
}
const ObjectBuilder *TStreamableTypes::Lookup( ModuleId,
const _TCHAR *name ) const
{
unsigned loc = Types.Find(&TStreamableClass(name,0,0,0));
if( loc == UINT_MAX )
{
string msg;
msg.reserve(128);
msg = "Attempt to stream unregistered type '";
msg += name;
msg += "'";
throw xmsg(msg);
}
return Types[loc];
}
void TPReadObjects::RemoveAll()
{
Data.Flush();
}
void TPReadObjects::RegisterObject( TStreamableBase *adr )
{
Data.Add( adr );
}
TStreamableBase *TPReadObjects::Find( P_id_type id )
{
return Data[id];
}
TPReadObjects::TPReadObjects() : Data(5,5)
{
Data.Add(0); // prime it: 0 is not a legal index.
}
TPWrittenObjects::TPWrittenObjects() : CurId(0), Data(5,5)
{
}
void TPWrittenObjects::RemoveAll()
{
CurId = 0; Data.Flush();
}
void TPWrittenObjects::RegisterObject( TStreamableBase *adr )
{
Data.Add( TPWObj( ((_TCHAR *)(void *)adr)+1, ++CurId ) );
}
void TPWrittenObjects::RegisterVB( const TStreamableBase *adr )
{
Data.Add( TPWObj( adr, ++CurId ) );
}
P_id_type TPWrittenObjects::FindObject( TStreamableBase *d )
{
unsigned res = Data.Find( TPWObj(((_TCHAR *)(void *)d)+1,0) );
if( res == UINT_MAX )
return 0;
else
return Data[res].Ident;
}
P_id_type TPWrittenObjects::FindVB( TStreamableBase *d )
{
unsigned res = Data.Find( TPWObj(d,0) );
if( res == UINT_MAX )
return 0;
else
return Data[res].Ident;
}
pstream::~pstream()
{
}
void pstream::initTypes()
{
if( types == 0 )
types = new TStreamableTypes;
}
void pstream::releaseTypes()
{
delete types;
types = 0;
}
streampos ipstream::tellg()
{
streampos res;
if( !good() )
res = streampos(EOF);
else
{
res = bp->seekoff( 0, ios::cur, ios::in );
if( res == streampos(EOF) )
clear( ios::failbit );
}
return res;
}
ipstream& ipstream::seekg( streampos pos )
{
if( good() )
{
objs.RemoveAll();
if( bp->seekoff( pos, ios::beg, ios::in ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
{
if( good() )
{
objs.RemoveAll();
if( bp->seekoff( off, dir, ios::in ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
uint8 ipstream::readByte()
{
int res;
if( !good() )
res = uint8(0);
else
{
res = bp->sbumpc();
if( res == EOF )
clear( ios::failbit );
}
return uint8(res);
}
void ipstream::readBytes( void *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
if( bp->sgetn( (_TCHAR *)data, sz ) != sz )
clear( ios::failbit );
}
}
void ipstream::freadBytes( void _BIDSFARDATA *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
_TCHAR *buf = new _TCHAR[sz];
if( bp->sgetn( buf, sz ) != sz )
clear( ios::failbit );
else
memcpy( data, buf, sz);
delete [] buf;
}
}
uint32 ipstream::readWord()
{
if( getVersion() > 0 )
return readWord32();
else
return readWord16();
}
uint16 ipstream::readWord16()
{
if( !good() )
return 0;
else
{
uint16 temp;
if( bp->sgetn( (_TCHAR *)&temp, sizeof( temp ) ) != sizeof( temp ) )
clear( ios::failbit );
return temp;
}
}
uint32 ipstream::readWord32()
{
if( !good() )
return 0;
else
{
uint32 temp;
if( bp->sgetn( (_TCHAR *)&temp, sizeof( temp ) ) != sizeof( temp ) )
clear( ios::failbit );
return temp;
}
}
uint32 ipstream::readStringLength()
{
uint32 len;
if( getVersion() > 0x0100 )
{
len = readWord32();
}
else
{
len = readByte();
if( len == oldNullStringLen )
len = nullStringLen;
}
return len;
}
_TCHAR *ipstream::readString()
{
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen )
return 0;
_TCHAR *buf = new _TCHAR[size_t(len+1)];
if( buf == 0 )
return 0;
readBytes( buf, size_t(len) );
buf[size_t(len)] = EOS;
return buf;
}
}
_TCHAR *ipstream::readString( _TCHAR *buf, unsigned maxLen )
{
PRECONDITION( buf != 0 );
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen || len > maxLen-1 )
return 0;
readBytes( buf, size_t(len) );
buf[size_t(len)] = EOS;
return buf;
}
}
_TCHAR _BIDSFARDATA *ipstream::freadString()
{
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen )
return 0;
_TCHAR _BIDSFARDATA *buf = new _BIDSFARDATA _TCHAR[size_t(len)+1];
freadBytes(buf, size_t(len));
buf[size_t(len)] = EOS;
return buf;
}
}
_TCHAR _BIDSFARDATA *ipstream::freadString( _TCHAR _BIDSFARDATA *buf, unsigned maxLen )
{
PRECONDITION(buf != 0 );
if( !good() )
return 0;
else
{
uint32 len = readStringLength();
if( len == nullStringLen || len > maxLen-1 )
return 0;
freadBytes( buf, size_t(len));
buf[size_t(len)] = EOS;
return buf;
}
}
void ipstream::readVersion()
{
if( !good() )
version = 0;
else
{
int res = bp->sgetc();
if( res == EOF )
{
clear( ios::eofbit );
version = 0;
return;
}
if( res != versionIndicator )
version = 0;
else
{
bp->sbumpc();
version = readWord32();
}
}
}
TStreamableBase _FAR *ipstream::readObject( TStreamableBase _FAR *&mem,
ModuleId mid )
{
if( good() )
{
const ObjectBuilder *pc = readPrefix( mid );
if( pc == 0 )
mem = 0;
else
{
readData( pc, mem );
readSuffix();
}
}
return mem;
}
const ObjectBuilder *ipstream::readPrefix( ModuleId mid )
{
_TCHAR ch = readByte();
if( ch != '[' )
{
clear( ios::failbit );
return 0;
}
_TCHAR name[128];
name[0] = EOS;
readString( name, sizeof name );
if( name[0] == EOS )
{
clear( ios::failbit );
return 0;
}
TRACEX(Objstrm,0,"Reading " << name);
const ObjectBuilder *res = types->Lookup( mid, name );
WARNX(Objstrm,res==0,0,"Unrecognized class identifier: " << name);
if( res == 0 )
{
clear( ios::failbit );
return 0;
}
return res;
}
void ipstream::readData( const ObjectBuilder *c, TStreamableBase _FAR *&mem )
{
TStreamer *strmr = c->Builder(mem);
mem = strmr->GetObject();
// register the address
registerObject( mem );
uint32 classVer = 0;
if( getVersion() > 0 )
classVer = readWord32();
strmr->Read( *this, classVer );
delete strmr;
}
void ipstream::readSuffix()
{
if( !good() )
return;
_TCHAR ch = readByte();
if( ch != ']' )
clear( ios::failbit );
}
TStreamableBase _FAR *ipstream::readObjectPointer( TStreamableBase _FAR *&mem,
ModuleId mid )
{
if( !good() )
return 0;
_TCHAR ch = readByte();
switch( ch )
{
case pstream::ptNull:
mem = 0;
break;
case pstream::ptIndexed:
{
P_id_type index = P_id_type(readWord());
mem = find( index );
CHECK( mem != 0 );
break;
}
case pstream::ptObject:
{
const ObjectBuilder *pc = readPrefix( mid );
readData( pc, mem );
readSuffix();
break;
}
default:
clear( ios::failbit );
break;
}
return mem;
}
opstream::opstream()
{
objs = new TPWrittenObjects;
if( bp != 0 )
writeVersion();
}
opstream::opstream( streambuf * sb )
{
objs = new TPWrittenObjects;
pstream::init( sb );
writeVersion();
}
streampos opstream::tellp()
{
streampos res;
if( !good() )
res = streampos(EOF);
else
{
res = bp->seekoff( 0, ios::cur, ios::out );
if( res == streampos(EOF) )
clear( ios::failbit );
}
return res;
}
opstream& opstream::seekp( streampos pos )
{
if( good() )
{
objs->RemoveAll();
if( bp->seekoff( pos, ios::beg, ios::out ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
{
if( good() )
{
objs->RemoveAll();
if( bp->seekoff( pos, dir, ios::out ) == streampos(EOF) )
clear( ios::failbit );
}
return *this;
}
void opstream::writeVersion()
{
if( good() )
{
writeByte( versionIndicator );
writeWord32( streamVersion );
}
}
opstream& opstream::flush()
{
if( bp->sync() == EOF )
clear( ios::badbit );
return *this;
}
void opstream::writeByte( uint8 ch )
{
if( good() )
{
if( bp->sputc( ch ) == EOF )
clear( ios::failbit );
}
}
void opstream::writeBytes( const void *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
if( bp->sputn( (_TCHAR *)data, sz ) != sz )
clear( ios::failbit );
}
}
void opstream::writeWord16( uint16 word16 )
{
if( good() )
{
if( bp->sputn( (_TCHAR *)&word16, sizeof(word16) ) != sizeof(word16) )
clear( ios::failbit );
}
}
void opstream::writeWord32( uint32 word32 )
{
if( good() )
{
if( bp->sputn( (_TCHAR *)&word32, sizeof(word32) ) != sizeof(word32) )
clear( ios::failbit );
}
}
void opstream::fwriteBytes( const void _BIDSFARDATA *data, size_t sz )
{
PRECONDITION( data != 0 );
if( good() && sz > 0 )
{
_TCHAR *buf = new _TCHAR[sz];
memcpy( buf, data, sz );
if( bp->sputn( (_TCHAR *)buf, sz ) != sz )
clear( ios::failbit );
delete[] buf;
}
}
void opstream::writeString( const _TCHAR *str )
{
if( !good() )
return;
if( str == 0 )
{
writeWord32( nullStringLen );
return;
}
size_t len = _tcslen( str );
writeWord32( len );
writeBytes( str, len );
}
void opstream::fwriteString( const _TCHAR _BIDSFARDATA * str )
{
if( !good() )
return;
if( str == 0 )
{
writeWord32( nullStringLen );
return;
}
size_t len = _tcslen( str );
writeWord32( len );
fwriteBytes(str, len);
}
#pragma warn -par
void opstream::writeObject( const TStreamableBase _FAR *mem, int isPtr, ModuleId mid )
{
WARNX(Objstrm,
!isPtr && findObject( CONST_CAST(TStreamableBase *,mem) ),
0,
"Pointer written before object: " \
<< _TYPENAME(mem) << '(' << (void _FAR *)mem << ')' );
if( good() )
{
writePrefix( mem );
writeData( mem, mid );
writeSuffix( mem );
}
}
#pragma warn +par
void opstream::writeObjectPointer( const TStreamableBase *t, ModuleId mid )
{
if( good() )
{
P_id_type index;
if( t == 0 )
writeByte( pstream::ptNull );
else if( (index = findObject( CONST_CAST(TStreamableBase *,t) )) != 0 )
{
writeByte( pstream::ptIndexed );
writeWord( index );
}
else
{
writeByte( pstream::ptObject );
writeObject( t, 1, mid );
}
}
}
void opstream::writePrefix( const TStreamableBase *t )
{
if( good() )
{
writeByte( '[' );
writeString( _TYPENAME(t) );
}
}
void opstream::writeData( const TStreamableBase *t, ModuleId mid )
{
if( good() )
{
registerObject( CONST_CAST(TStreamableBase *,t) );
const ObjectBuilder *res = types->Lookup( mid, _TYPENAME(t) );
CHECKX(res,_TYPENAME(t));
TStreamer *strmr = res->Builder(CONST_CAST(TStreamableBase *,t));
writeWord32( strmr->ClassVersion() );
strmr->Write( *this );
delete strmr;
}
}
void fpbase::open( const _TCHAR *b, int m, int prot )
{
if( buf.is_open() )
clear(ios::failbit); // fail - already open
else if( buf.open(b, m, prot) )
clear(ios::goodbit); // successful open
else
clear(ios::badbit); // open failed
}
void fpbase::attach( int f )
{
if( buf.is_open() )
clear(ios::failbit);
else if( buf.attach(f) )
clear(ios::goodbit);
else
clear(ios::badbit);
}
void fpbase::close()
{
if( buf.close() )
clear(ios::goodbit);
else
clear(ios::failbit);
}
void fpbase::setbuf(_TCHAR* b, int len)
{
if( buf.setbuf(b, len) )
clear(ios::goodbit);
else
clear(ios::failbit);
}
//
// These operators are not friends of string, so
// they must use only the public interface.
//
#if defined(BI_NAMESPACE)
namespace ClassLib {
#endif
opstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator << ( opstream _BIDSFAR& os,
const string _BIDSFAR& str )
{
os.writeString( str.c_str() );
return os;
}
ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is,
string _BIDSFAR& str )
{
if( is.good() )
{
uint32 len = is.readStringLength();
if( len == nullStringLen )
str = "";
else
{
_TCHAR *temp = new _TCHAR[size_t(len)+1];
is.readBytes( temp, size_t(len) );
temp[size_t(len)] = EOS;
str = temp;
delete [] temp;
}
}
return is;
}
#if defined(BI_NAMESPACE)
} // namespace ClassLib
#endif